package com.lfy.modules.common.exception;

import com.lfy.modules.common.domain.BaseEnum;
import com.lfy.modules.common.domain.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.async.AsyncRequestTimeoutException;
import org.springframework.web.multipart.MultipartException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.stream.Collectors;
/**
 *  全局异常
 *
 * @author <a href="https://www.lvfeiy.top">lvfeiyang</a>
 * @date 2024/4/25 1:04
 */
@Slf4j
@RestControllerAdvice
public class GlobalException {
    /**
     * 文件大小限制异常
     */
    @ExceptionHandler(value = MultipartException.class)
    public R fileUploadExceptionHandler(MultipartException exception) {
        String msg = "";
        Throwable rootCase = exception.getRootCause();
        if (rootCase instanceof org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException) {
            msg = "上传文件过大[文件大小不得超过" + "1GB" + "]";
        } else if (rootCase instanceof org.apache.tomcat.util.http.fileupload.impl.SizeLimitExceededException) {
            msg = "文件上传失败[请求字节超限]";
        } else {
            msg = "上传失败[文件不合法]";
        }
        log.error(msg, exception);
        return R.error(msg, 500);
    }

    /**
     * GET POST
     */
    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
    public R fourZeroFiveError(HttpRequestMethodNotSupportedException e) {
        return R.error(BaseEnum.commonEnum.POST_OR_GET);
    }

    /**
     * validation参数校验异常
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public R methodArgumentNotValidExceptionExceptionHandler(MethodArgumentNotValidException e) {
        StringBuilder errorMsg = new StringBuilder();
        e.getBindingResult().getFieldErrors().forEach(x -> errorMsg.append(x.getField()).append(x.getDefaultMessage()).append(","));
        String message = errorMsg.toString();
        log.info("validation parameters error！The reason is:{}", message);
        return R.error(message.substring(0, message.length() - 1), BaseEnum.commonEnum.PARAM_VALID.getCode());
    }

    /**
     * validation参数校验异常
     */
    @ExceptionHandler(value = BindException.class)
    public R bindException(BindException e) {
        StringBuilder errorMsg = new StringBuilder();
        e.getBindingResult().getFieldErrors().forEach(x -> errorMsg.append(x.getField()).append(x.getDefaultMessage()).append(","));
        String message = errorMsg.toString();
        log.info("validation parameters error！The reason is:{}", message);
        return R.error(message.substring(0, message.length() - 1), BaseEnum.commonEnum.PARAM_VALID.getCode());
    }

    /**
     *validation参数校验异常
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public R<Void> constraintViolationException(Exception ex) {
        ConstraintViolationException c = (ConstraintViolationException) ex;
        String result = c.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining());

        return R.error(result);
    }

    /**
     * requestParam 参数缺失
     * @param e MissingServletRequestParameterException
     * @return r
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public R<Void> missingServletRequestParameterException(MissingServletRequestParameterException e){

        return R.error(e.getMessage());
    }


    /**
     * 处理空指针的异常
     */
    @ExceptionHandler(value = NullPointerException.class)
    public R<Void> exceptionHandler(NullPointerException e) {
        log.error("空指针异常", e);
        return R.error(BaseEnum.commonEnum.SYSTEM_ERROR.getMsg());
    }

    @ExceptionHandler(value = AsyncRequestTimeoutException.class)
    public void asyncRequestException(AsyncRequestTimeoutException e) {
        log.error("连接超时");
    }
    @ExceptionHandler(value = IllegalArgumentException.class)
    public R<Void> illegalArgumentException(AsyncRequestTimeoutException e) {
        return R.error(e.getMessage());
    }
    /**
     * 未知异常
     */
    @ExceptionHandler(value = Exception.class)
    public R<Void> systemExceptionHandler(Exception e) {
        log.error("未知异常", e);
        return R.error(BaseEnum.commonEnum.SYSTEM_ERROR);
    }

}
